//  /*******************************************************************************
//  * Author      :  ChuanQin Yu                                                   *
//  * Copyright   :  (c) ChuanQin Yu 2023-2023                                     *
//  * mail        :  ycq1014@gmail.com                                             *
//  * License     :  http://www.boost.org/LICENSE_1_0.txt                          *
//  ********************************************************************************

/**
 * @Author: ycq1014@gmail.com
 * @DATE: 2023/12/18
 * @Description:
*/
#ifndef LOGGER_H
#define LOGGER_H
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>
#include <string>

#include <boost/format.hpp>
#include <fstream>
#include "console.color.h"
#include "logger.version.h"

namespace mxg::Log{

#define debug(format, ...) \
		Logger::getInstance()->logPrint(MXG_LOGO, Logger::DEBUG, __DATE__, __TIME__, __FILE__, __LINE__, format, ##__VA_ARGS__);

#define info(format, ...) \
        Logger::getInstance()->logPrint(MXG_LOGO, Logger::INFO, __DATE__, __TIME__, __FILE__, __LINE__, format, ##__VA_ARGS__);

#define warn(format, ...) \
        Logger::getInstance()->logPrint(MXG_LOGO, Logger::WARN, __DATE__, __TIME__, __FILE__, __LINE__, format, ##__VA_ARGS__);

#define error(format, ...) \
        Logger::getInstance()->logPrint(MXG_LOGO, Logger::ERROR, __DATE__, __TIME__, __FILE__, __LINE__, format, ##__VA_ARGS__);

#define fatal(format, ...) \
        Logger::getInstance()->logPrint(MXG_LOGO, Logger::FATAL, __DATE__, __TIME__, __FILE__, __LINE__, format, ##__VA_ARGS__);

class Logger
{
public:
    enum Level{
        DEBUG = 0,
        INFO = 1,
        WARN = 2,
        ERROR = 3,
        FATAL = 4,
        LEVEL_COUNT
    };

    static const char* s_level[LEVEL_COUNT];
public:
    static Logger * getInstance();

    void logPrint(std::string_view logo,
                  Level level,
                  std::string_view date,
                  std::string_view time,
                  std::string fileName,
                  int codeLine,
                  const char* format,
                  ...);

    void setLevel(Level level)
    {
        m_level = level;
    }

    void setM_max(int mMax)
    {
        m_max = mMax;
    }

    void setFILE_LOG(bool fileLog)
    {
        FILE_LOG = fileLog;
    }

    void setNET_LOG(bool netLog)
    {
        NET_LOG = netLog;
    }

    // 重载配置函数
    void init(Level level);
    void init(Level level, int mMax);
    void init(Level level, int mMax, bool fileLog, bool netLog);
    void init(Level level, bool fileLog, bool netLog);
    void init(int mMax);
    void init(int mMax, bool fileLog, bool netLog);
    void init(bool fileLog, bool netLog);

protected:
    Logger();
    ~Logger();

private:
    static void setColor(const char* color);

    static std::string_view getColor(Level level);

    void openFile();

    void printFile(const std::string& format);

    void close();

    // 文件内容太多时，重新命名新文件
    void reName();

//    static std::size_t getLines(std::filebuf &m_fileBuf);

private:
    // 文件名
    std::string m_fileName {"Log_"};
    std::string FILENAME_ {"Log_"};

    // 文件缓冲区
    std::filebuf m_fileBuf{};

    // 文件流
    std::fstream m_fileStream{};

    // 日志等级
    Level m_level{};

    static Logger* m_instance;

    // 文件最大长度
    int m_max{1000};

    // 日志长度
    int m_len{};

    std::mutex m_mutex{};

    // 是否写入文件
    bool FILE_LOG = true;

    // 是否网络传输
    bool NET_LOG = false;
};
}

#endif //LOGGER_H
